#pragma once

#include "local_registry_common.hpp"

struct local_client;

// 服务项
struct local_service_item
{
    uint32_t service_id;                                                   // 服务ID
    uint32_t service_type;                                                 // 服务类型 see local_service_type
    uint32_t service_status;                                               // 服务状态 see local_service_status
    std::shared_ptr<local_client> service_provider;                        // 服务提供者
    std::unordered_map<uint32_t, std::shared_ptr<local_client>> listeners; // 监听该服务的消费者列表(client id)
};

// 客户端
struct local_client
{
    uint32_t client_id;                                                                 // 客户端进程ID(服务注册中心分配)
    pid_t client_pid;                                                                   // 客户端进程PID
    hio_t *client_io;                                                                   // 客户端进程fd
    std::string client_name;                                                            // 客户端进程名
    std::string client_localaddr;                                                       // 客户端进程本地unix socket地址
    local_client_status client_status;                                                  // 客户端进程运行状态
    std::unordered_map<uint32_t, std::shared_ptr<local_service_item>> produce_services; // 提供服务列表
    // std::unordered_map<uint32_t, std::shared_ptr<local_service_item>> consume_services; // 监听服务列表
};

// 服务注册中心
class LocalRegistry
{
    SINGLETON_DECL(LocalRegistry);

protected:
    LocalRegistry();
    ~LocalRegistry();

private:
    static hloop_t *get_idle_loop();
    static void on_close(hio_t *io);
    static void on_recv(hio_t *io, void *buf, int readbytes);
    static void on_write(hio_t *io, const void *buf, int writebytes);
    static void on_accept(hio_t *io);
    static void on_post_event_cb(hevent_t *ev);
    std::int32_t send_msg_to_client(hio_t *client_io, uint32_t msg_id, const void *msgdata, const pb_msgdesc_t *fileds, uint32_t field_size);

    std::int32_t add_client(std::string client_localaddr, hio_t *client_io);
    std::int32_t remove_client(hio_t *client_io);
    std::int32_t register_client(st_register_client_req *req, hio_t *io);
    std::int32_t get_client(st_get_client_req *req, hio_t *io);
    std::int32_t get_listener(st_get_listener_req *req, hio_t *io);
    std::int32_t register_service(st_register_service *msg);
    std::int32_t listen_service(st_listen_service *msg);
    std::int32_t get_service(st_get_service_req *req);
    std::int32_t service_set_status(st_service_set_status *msg);
    std::int32_t ctr_get_clients(hio_t *io);
    std::int32_t ctr_get_services(hio_t *io);

    std::string m_localaddr; // bind localaddr

    // one accepter
    hloop_t *accept_loop;
    hio_t *listen_io;
    hio_t *ctrl_io;
    std::thread accept_thread;

    // mult worker
    hloop_t **worker_loops;
    std::vector<std::thread> worker_threads;
    std::mutex m_worker_mutex;
    unpack_setting_t unpack_setting;

    std::atomic_uint32_t next_client_id{1};                                           // 分配clientID
    std::unordered_map<std::string, std::shared_ptr<local_client>> m_clients_by_name; // 客户端列表(process name)
    std::unordered_map<uint32_t, std::shared_ptr<local_service_item>> m_services;     // 服务列表
    std::mutex m_unorderedmap_mutex;
};
